import type { LoginInfo } from "/#/store"
import type { ErrorMessageMode } from "/#/axios"
import { h, defineAsyncComponent } from 'vue'
import { defineStore } from "pinia"
import { store } from "/@/store"
import { RoleEnum } from "/@/enums/roleEnum"
import { PageEnum } from "/@/enums/pageEnum"
import { ROLES_KEY, LAST_ROUTE_PATH, USER_INFO_KEY, DB_DICT_DATA_KEY } from "/@/enums/cacheEnum"
import * as authCache from "/@/utils/cache/module"
import { getCache, setCache, setCacheByDynKey, getCacheByDynKey } from "/@/utils/cache/index"
import { GetUserInfoModel, UserInfo, LoginParams, ThirdLoginParams } from "/@/api/sys/model/userModel"
import { getRouteAllPath } from "/@/router/helper/routeHelper"
import { AuthInfo, TenantConfig } from "/@/model"
import { getUserInfo, phoneLoginApi, thirdLogin } from "/@/api/sys/user"
import * as authApi from "/@/api/auth/index"
import { useI18n } from "/@/hooks/web/useI18n"
import { useMessage } from "/@/hooks/web/useMessage"
import { router } from "/@/router"
import { usePermissionStore } from "/@/store/modules/permission"
import { RouteRecordRaw } from "vue-router"
import { PAGE_NOT_FOUND_ROUTE } from "/@/router/routes/basic"
import { getPathFromUrl, isArray, listAllUrlParam } from "/@/utils"
import { getTenantId, setLastTenantId } from "/@/utils/tenant"
import { useGlobSetting } from "/@/hooks/setting"
import { useIam } from "/@/hooks/web/useIam"
import { queryAllDictItems } from "/@/api/infra/dict"
import { switchTenant } from "/@/api/sys/user"
import mitt, { Emitter } from "/@/utils/mitt"
import * as iamCache from "/@/utils/cache/module/iam"
import { TenantType } from "/@/enums/bizEnum"
import pubsub from "pubsub-js"
import { getTenant } from "/@/api/sys/tenant"
import { Modal } from "ant-design-vue"

const NoAuthTips = defineAsyncComponent(async () => {
  return await import('/@/components/My/noAuth/NoAuthTips.vue')
})
const glob = useGlobSetting()
const { createMessage, notification, createErrorModal } = useMessage()

// import { useRedo } from '/@/hooks/web/usePage';
// const redo = useRedo();
interface UserState {
  showPermApplyTips: boolean
  userInfo?: UserInfo
  selectTenant?: TenantConfig
  tokenInfo?: AuthInfo
  token?: string
  roleList: RoleEnum[]
  dictItems?: []
  sessionTimeout?: boolean
  lastUpdateTime: number
  multiDept?: string | number
  deptList?: []
  tenantList?: []
  isLogin: boolean
  emitter: Emitter
}

/**
 * 获取数据的时候, 一定要先从store中获取, 获取不到再从浏览器本地缓存获取, 或者直接获取store即可,
 * 不可只获取浏览器本地缓存中数据
 *
 * 这样可以避免一个浏览器打开多个租户时数据错乱问题, 比如你打开两个tab, 新打开的tab肯定会加载整个应用
 * , 那么浏览器本地中的缓存数据就是最后刷新的tab数据, 如果先从store获取, 切换到另一个标签且没有刷新tab所在页面
 * 时候, 如果直接获取浏览器本地缓存数据, 会出现获取到的数据错乱问题
 */
export const useUserStore = defineStore({
  id: "app-user",
  state: (): UserState => ({
    // 是否正在权限申请中
    showPermApplyTips: false,
    // 用户信息
    userInfo: undefined,
    tokenInfo: undefined,
    selectTenant: undefined,
    // 角色列表
    roleList: [],
    // 字典
    dictItems: [],
    // session过期时间
    sessionTimeout: false,
    // Last fetch time
    lastUpdateTime: 0,
    isLogin: false,
    // 全局事件 think gem
    emitter: mitt(),
  }),
  getters: {
    getShowPermApplyTips(): boolean {
      return this.showPermApplyTips
    },
    getUserInfo(): UserInfo {
      return this.userInfo || authCache.getUserInfo() || {}
    },
    getTokenInfo(): AuthInfo {
      return this.tokenInfo || iamCache.getTokenInfo() || {}
    },
    getSelectTenant(): TenantConfig {
      const tenantInfo = this.selectTenant || authCache.getSelectTenant() || {}
      tenantInfo.isMainTenant = tenantInfo.tenantType == TenantType.MAIN
      return tenantInfo
    },

    getIsSysAdminTenant(): boolean {
      // const tenant = getCacheByDynKey<TenantConfig>(TENANT_CONFIG_KEY) || {}
      // todo sgy
      return false
    },

    getToken(): string | undefined {
      this.tokenInfo = this.tokenInfo || iamCache.getTokenInfo()
      return this.tokenInfo?.accessToken
    },
    getAllDictItems(): [] {
      return this.dictItems || getCache(DB_DICT_DATA_KEY)
    },
    getRoleList(): RoleEnum[] {
      return this.roleList.length > 0 ? this.roleList : getCache<RoleEnum[]>(ROLES_KEY)
    },
    getSessionTimeout(): boolean {
      return !!this.sessionTimeout
    },
    getLastUpdateTime(): number {
      return this.lastUpdateTime
    },
    getIsLogin(): boolean {
      return !!this.isLogin
    },
    getEmitter(): any {
      return this.emitter
    },
  },
  actions: {
    requestNoAuthTips(data: any): void {
      const { t } = useI18n()
      if (this.showPermApplyTips) {
        console.log('发布预备权限申请消息', data)
        pubsub.publish("readyPermApply", data)
      } else {
        this.showPermApplyTips = true
        createErrorModal({
          title: '无权限',
          content: h(NoAuthTips, { data }),
          okCancel: false,
          okText: '关闭',
          afterClose: () => {
            this.showPermApplyTips = false
          },
        })
      }

    },
    setShowPermApplyTips(value: boolean): void {
      this.showPermApplyTips = value
    },
    setToken(token: string | undefined) {
      this.tokenInfo = this.tokenInfo || {}
      this.tokenInfo.accessToken = token
      iamCache.setTokenInfo({
        accessToken: token,
      })
    },
    setTokenInfo(info: AuthInfo | undefined) {
      this.tokenInfo = info ? { ...this.tokenInfo, ...(info || {}) } : undefined
      iamCache.setTokenInfo(this.tokenInfo)
    },

    /**
     * 设置选择的租户
     */
    async setSelectTenant(tenantInfo: any) {
      const tenantId = tenantInfo?.id

      this.selectTenant = tenantInfo
      if (tenantId) {
        setLastTenantId(tenantId)
      }

      iamCache.setSelectTenant(tenantInfo)
    },

    // 切换租户
    async switchTenant(tenantId: string) {
      const resp = await switchTenant({ tenantId })
      await this.setSelectTenant({ ...resp })
    },

    // 前一个工作空间最后一次的路由
    setLastRoutePath(info: string | undefined) {
      setCacheByDynKey(LAST_ROUTE_PATH + this.userInfo?.currentTenantId + this.userInfo?.currentAppId, info)
    },
    setRoleList(roleList: RoleEnum[]) {
      this.roleList = roleList
      authCache.setRole(roleList)
    },
    setUserInfo(info: UserInfo | undefined) {
      this.userInfo = info
      this.lastUpdateTime = new Date().getTime()
      authCache.setUserInfo(info)
    },
    setAllDictItems(dictItems) {
      this.dictItems = dictItems
      authCache.setDictItems(dictItems)
    },
    setSessionTimeout(flag: boolean) {
      this.sessionTimeout = flag
    },
    resetState() {
      this.userInfo = undefined
      this.dictItems = []
      this.token = ""
      this.roleList = []
      this.sessionTimeout = false
      const tenantId = getTenantId()
    },

    /**
     * 登录完成处理
     * @param goHome
     */
    async afterLoginAction(goHome?: boolean, authLoginData?: any): Promise<any | null> {
      const queryParams: any = listAllUrlParam() || {}
      console.log("============== authLoginData", authLoginData, queryParams)

      console.time("load_menu_time")
      if (!this.getToken) {
        console.warn("token is null")
        return null
      }

      if (!authLoginData.tenantId) {
        console.warn("tenantId is null")
        return null
      }

      const tenantInfo = await getTenant({ id: authLoginData.tenantId })
      this.setSelectTenant(tenantInfo)

      //获取用户信息
      const useProfile = await this.getUserInfoAction()
      const sessionTimeout = this.sessionTimeout
      if (sessionTimeout) {
        this.setSessionTimeout(false)
      } else {
        const redirect = queryParams?.redirect as string
        let pagePath = redirect || (useProfile && useProfile.userInfo?.homePath) || PageEnum.BASE_HOME
        pagePath = getPathFromUrl(pagePath)

        console.log("pagePath", pagePath)

        const permissionStore = usePermissionStore()
        if (!permissionStore.isDynamicAddedRoute) {
          const routes = await permissionStore.buildRoutesAction()

          routes.forEach((route) => {
            router.addRoute(route as unknown as RouteRecordRaw)
          })
          router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw)
          permissionStore.setDynamicAddedRoute(true)

          const routeAllPath = getRouteAllPath(routes)
          if (routeAllPath.indexOf(pagePath.split('?')[0]) == -1) {
            console.log('租户可能已被切换, 路径不存在, pagePath: ', pagePath)
            pagePath = PageEnum.BASE_HOME
          }
        }
        this.isLogin = true

        // @ts-ignore
        authCache.setUserInfo(useProfile?.userInfo)
        this.setTokenInfo({ isLogin: true })
        console.timeEnd("load_menu_time")

        goHome &&
          (await router.replace({
            path: pagePath === "/" || pagePath === "" ? PageEnum.BASE_HOME : pagePath,
          }))
      }
      return authLoginData
    },

    /**
     * 获取用户信息
     */
    async getUserInfoAction(): Promise<GetUserInfoModel | null> {
      const data = (await getUserInfo()) as GetUserInfoModel || {}
      const { roles, userInfo } = data
      // this.setSelectTenant(tenant)
      if (roles) {
        if (isArray(roles)) {
          const roleList = roles.map((item) => item.value) as RoleEnum[]
          this.setRoleList(roleList)
        } else {
          this.setRoleList([])
        }
      }
      this.setUserInfo(userInfo as UserInfo)
      const sysAllDictItems = await queryAllDictItems()
      // 添加字典信息到缓存
      if (sysAllDictItems && sysAllDictItems.data) {
        this.setAllDictItems(sysAllDictItems.data)
      }
      console.log("userInfo: ", userInfo)
      return data
    },

    /**
     * 退出登录
     */
    async logout(isConfirm = false) {
      console.log("logout")

      try {
        this.setToken(undefined)
        this.setSessionTimeout(false)
        // 你自己的业务系统退出
        await useIam().ssoLogout()
        // await iamCache.initPublicConfig()
      } catch (e) {
        console.error("注销Token失败", e)
      } finally {
        this.setUserInfo(undefined)
        this.resetState()
        this.setSelectTenant(null)
      }

      const iam = useIam({
        loginTimoutCallback: (url) => {
          Modal.confirm({
            content: "登录态已过期，请重新登录",
            iconType: "warning",
            closable: false,
            visible: true,
            cancelButtonProps: { style: { display: "none" } }, // 隐藏取消按钮
            okText: "重新登录",
            onOk: () => {
              setTimeout(() => {
                window.location.href = url
              }, 200)
            }
          })
        }
      })
      iam.redirectLogin(isConfirm)
    },
  
    /**
     * 退出询问
     */
    confirmLoginOut() {
      const { createConfirm } = useMessage()
      const { t } = useI18n()
      createConfirm({
        iconType: "warning",
        title: t("sys.app.logoutTip"),
        content: t("sys.app.logoutMessage"),
        onOk: async () => {
          await this.logout(false)
        },
      })
    },
  },
})

// Global emit by think gem
export function useEmitter() {
  return useUserStore().emitter
}

// Need to be used outside the setup
export function useUserStoreWithOut() {
  return useUserStore(store)
}
